/* Nate Deisinger (ndeisinger@wisc.edu)
 *
 * This file is part of soot-csi, a project to apply lightweight
 * instrumentation to Java programs to facilitate debugging through
 * the Soot analysis framework.
 *
 * Copyright (c) 2014, Nate Deisinger, University of Wisconsin-Madison
 *   Madison, Wisconsin 53715
 *   All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor,
 *   Boston, MA  02110-1301
 *   USA
 * or retrieve version 2.1 at their website:
 *   http://www.gnu.org/licenses/lgpl-2.1.html
 */
package uwmadison.jpdg;
import java.io.*;
import java.util.LinkedList;
import java.util.Scanner;

import soot.jimple.DefinitionStmt;

import com.tinkerpop.blueprints.*;
import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
import com.tinkerpop.blueprints.util.io.graphml.*;
import com.tinkerpop.blueprints.util.io.graphson.*;

/**
 * Utility classes to convert our JSON-based graphs to 
 * the GraphML language.
 * 
 * Requires the Blueprints graph manipulation library
 * (https://github.com/tinkerpop/blueprints/wiki/GraphML-Reader-and-Writer-Library)
 */
public class GraphParser {

    /**
     * Parses a Blueprint-based graph to GraphML
     */
    public static void parseJSONToGraphML(String infile, String outfile) throws IOException
    {
        Graph graph = new TinkerGraph();
        InputStream in = new FileInputStream(new File(infile));
        OutputStream out = new FileOutputStream(new File(outfile));
        GraphSONReader.inputGraph(graph, in);
        GraphMLWriter.outputGraph(graph, out);        
    }
    
    /**
     * Parses our PDG to a NetworkX-compatible JSON format.
     */
    public static void parsePDGtoNetX (String inpath, String outpath) throws IOException
    {
        Scanner in = new Scanner(new File(inpath));
        LinkedList<String> nodes = new LinkedList<String>();
        LinkedList<String> edges = new LinkedList<String>();
        while (in.hasNextLine())
        {
            String val = in.nextLine();
            if (val.startsWith("vertex", 0))
            {
                nodes.add(val.substring(7));
            }
            else if(val.startsWith("edge", 0))
            {
                String edge = val.substring(5).replace("\"src\":", "\"source\":");
                edge = edge.replace("\"targ\":", "\"target\":");
                edges.add(edge);
            }
        }
        PrintWriter out = new PrintWriter(new FileWriter(
                new File(outpath)));
        out.write("{\"directed\": true, \"graph\": [[\"node_default\", {\"kind\": \"declaration\"}], [\"edge_default\", {\"type\": \"flow\", \"when\": \"true\", \"scope\": \"intraprocedural\"}]],");
        out.write("\"nodes\": [");
        boolean first = true;
        for (String s : nodes)
        {
            if(!first)
            {
                out.write(",");
            }
            first = false;
            out.write(s);
        }
        out.write("],");
        out.write("\"links\": [");
        first = true;
        for (String s : edges)
        {
            if(!first)
            {
                out.write(",");
            }
            first = false;
            out.write(s);
        }
        out.write("], \"multigraph\": true}");
        out.flush();
        out.close();
    }

    /**
     * Parses our PDG to a Blueprints GraphSON-compatible format.
     */
    public static void parsePDGtoBlue (String inpath, String outpath) throws IOException
    {
        Scanner in = new Scanner(new File(inpath));
        LinkedList<String> nodes = new LinkedList<String>();
        LinkedList<String> edges = new LinkedList<String>();
        while (in.hasNextLine())
        {
            String val = in.nextLine();
            if (val.startsWith("vertex", 0))
            {
                String edge = val.substring(7).replace("\"id\":", "\"_id\":");
                nodes.add(edge);
            }
            else if(val.startsWith("edge", 0))
            {
                String edge = val.substring(5).replace("\"src\":", "\"_outV\":");
                edge = edge.replace("\"targ\":", "\"_inV\":");
                edge = edge.replace("label", "type");
                edges.add(edge);
            }
        }
        PrintWriter out = new PrintWriter(new FileWriter(
                new File(outpath)));
        out.write("{\n" + 
                "    \"graph\": {\n" + 
                "        \"mode\":\"NORMAL\",\n" + 
                "        \"vertices\": [");
        boolean first = true;
        for (String s : nodes)
        {
            if(!first)
            {
                out.write(",");
            }
            first = false;
            out.write(s);
        }
        out.write("],");
        out.write("\"edges\": [");
        first = true;
        for (String s : edges)
        {
            if(!first)
            {
                out.write(",");
            }
            first = false;
            out.write(s);
        }
        out.write("] \n}\n" + 
                "}");
        out.flush();
        out.close();
    }
}
